﻿using System.Linq;
using System.Windows;
using System.Windows.Controls;
using DependencyAnalysis.DataModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace XamlTests
{
    [TestClass]
    public class ResourceDictionaryTest : XamlTestBase
    {
        private ModuleDescriptor _module;
        private TypeDescriptor _dictionary11;
        private TypeDescriptor _dictionary1;
        private TypeDescriptor _dictionary2;
        private TypeDescriptor _dictionary21;
        private TypeDescriptor _userControl;
        private TypeDescriptor _appXaml;

        [TestInitialize]
        public void Initialize()
        {
            _module = DescriptorBuilder.BuildModuleDescriptor(typeof(WpfControlLibrary1.Properties.IAssemblyIdentifier).Assembly);
            _dictionary11 = new TypeDescriptor { Identifier = _module.Identifier + " /type WpfControlLibrary1.sublevel.dictionary11.xaml" };
            _dictionary1 = new TypeDescriptor { Identifier = _module.Identifier + " /type WpfControlLibrary1.dictionary1.xaml" };
            _dictionary2 = new TypeDescriptor { Identifier = _module.Identifier + " /type WpfControlLibrary1.dictionary2.xaml" };
            _userControl = new TypeDescriptor { Identifier = _module.Identifier + " /type WpfControlLibrary1.UserControl1.xaml" };
            _dictionary21 = new TypeDescriptor { Identifier = _module.Identifier + " /type WpfControlLibrary1.sublevel.dictionary21.xaml" };
            _appXaml = new TypeDescriptor { Identifier = _module.Identifier + " /type WpfControlLibrary1.app.xaml" };
        }

        [TestMethod]
        public void CreateNamespaceForFolderWithXaml()
        {
            var sublevel = DescriptorBuilder.BuildSubmoduleDescriptor(_module, "WpfControlLibrary1.sublevel");
            Assert.IsTrue(Model.DependenciesPerSubmodule.ContainsKey(sublevel));
        }

        [TestMethod]
        public void CreateTypeForXaml()
        {
            Assert.IsTrue(Model.DependenciesPerType.ContainsKey(_dictionary11));
        }

        [TestMethod]
        public void XamlReferencesResourceDictionary()
        {
            var resourceDictionary = typeof(ResourceDictionary);
            var typeDescriptor = DescriptorBuilder.BuildTypeDescriptor(resourceDictionary);

            Assert.IsTrue(Verifier.RefersTo(_dictionary11, typeDescriptor));
        }

        [TestMethod]
        public void WhenMergedDictionariesPackUriThenReferToOtherXaml()
        {
            Assert.IsTrue(Verifier.RefersTo(_dictionary1, _dictionary2));
        }

        [TestMethod]
        public void WhenMergedDictionariesAbsoluteUriThenReferToOtherXaml()
        {
            Assert.IsTrue(Verifier.RefersTo(_dictionary1, _dictionary11));
        }
        [TestMethod]
        public void WhenXamlThenTypeIsDescriptive()
        {
            var descriptor = Model.DependenciesPerType.Keys.First(x => Equals(x, _dictionary11));

            Assert.AreEqual(AbstractionType.Descriptive, ((TypeDescriptor)descriptor).AbstractionType);
        }

        [TestMethod]
        public void WhenElementThenReferToElementType()
        {
            var resourceDictionary = typeof(Style);
            var typeDescriptor = DescriptorBuilder.BuildTypeDescriptor(resourceDictionary);

            Assert.IsTrue(Verifier.RefersTo(_dictionary11, typeDescriptor));
        }

        [TestMethod]
        public void WhenElementPropertyThenReferToTargetProperty()
        {
            var type = typeof(StackPanel);
            var member = type.GetMember("Orientation");
            var memberDescriptor = DescriptorBuilder.BuildMemberDescriptor(member[0]);

            Assert.IsTrue(Verifier.RefersTo(_dictionary11, memberDescriptor));
        }

        [TestMethod]
        public void WhenStaticResourceThenCreateRefereneBetweenElements()
        {
            var descriptor = (TypeDescriptor)Model.DependenciesPerType.First(x => Equals(x.Key, _dictionary11)).Key;
            var template = descriptor.Members.First(x => x.Name == "TestTemplate");

            var dependencies = Model.DependenciesPerMember[template];
            Assert.IsTrue(dependencies.Any(x => x.Source.Name == "ItemsControl'1"));
        }

        [TestMethod]
        public void WhenStaticResourceThenResolveInMergedDictionaries()
        {
            var brushMember = DescriptorBuilder.BuildXamlMemberDescriptor(_dictionary2, "brush1");

            Assert.IsTrue(Verifier.RefersTo(_dictionary1, brushMember));
        }

        [TestMethod]
        public void WhenBindingToElementNameThenCreateReferenceBetweenElements()
        {
            var itemsControl = DescriptorBuilder.BuildXamlMemberDescriptor(_dictionary11, "ItemsControl'1");
            var button = DescriptorBuilder.BuildXamlMemberDescriptor(_dictionary11, "SomeButton");


            Assert.IsTrue(Verifier.RefersTo(itemsControl, button));
        }

        [TestMethod]
        public void WhenElementHasNameThenSetName()
        {
            var descriptor = (TypeDescriptor)Model.DependenciesPerType.First(x => Equals(x.Key, _dictionary11)).Key;
            Assert.IsTrue(descriptor.Members.Any(x => x.Name == "SomeText"));
        }

        [TestMethod]
        public void WhenElementHasKeyThenSetName()
        {
            var descriptor = (TypeDescriptor)Model.DependenciesPerType.First(x => Equals(x.Key, _dictionary11)).Key;
            Assert.IsTrue(descriptor.Members.Any(x => x.Name == "TestTemplate"));
        }

        [TestMethod]
        public void WhenNeitherNameNorKeyThenCreateGenericMemberName()
        {
            var descriptor = (TypeDescriptor)Model.DependenciesPerType.First(x => Equals(x.Key, _dictionary11)).Key;
            Assert.IsTrue(descriptor.Members.Any(x => x.Name == "ItemsControl'1"));
        }

        [TestMethod]
        public void WhenResourceIsPresentInTwoDictionariesThenReferToCorrectOne()
        {
            var brushMember2 = DescriptorBuilder.BuildXamlMemberDescriptor(_dictionary2, "brush1");
            var brushMember21 = DescriptorBuilder.BuildXamlMemberDescriptor(_dictionary21, "brush1");

            Assert.IsTrue(Verifier.RefersTo(_userControl, brushMember21));
            Assert.IsTrue(Verifier.RefersTo(_dictionary1, brushMember2));
        }
    }
}
